package com.ruoyi.fee.service.impl;



import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.dto.BillPayStatusDTO;
import com.ruoyi.common.core.dto.PayRequestDTO;
import com.ruoyi.common.core.dto.PayResponseDTO;
import com.ruoyi.common.core.dto.PayStatusDTO;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.fee.domain.PropertyBill;
import com.ruoyi.fee.domain.PropertyPayment;
import com.ruoyi.fee.mapper.PropertyBillMapper;
import com.ruoyi.fee.mapper.PropertyPaymentMapper;
import com.ruoyi.fee.service.PayService;
import com.ruoyi.system.domain.PropertyHouse;
import com.ruoyi.system.mapper.PropertyHouseMapper;




import com.ruoyi.common.utils.SecurityUtils;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 支付服务实现类（整合微信支付、支付宝支付）
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {

    // 微信支付相关

    @Value("${wechat.pay.appid}")
    private String wechatAppId;
    @Value("${wechat.pay.merchant-id}")
    private String wechatMerchantId;
    @Value("${wechat.pay.api-v3-key}")
    private String wechatApiV3Key;
    @Value("${wechat.pay.private-key-path}")
    private String privateKeyPath; // 私钥路径（apiclient_key.pem）


    @Value("${alipay.appid}")
    private String alipayAppId;
    @Value("${alipay.private-key}")
    private String alipayPrivateKey;
    @Value("${alipay.public-key}")
    private String alipayPublicKey;
    @Value("${alipay.returnUrl}")
    private String returnUrl;
    @Value("${alipay.notifyUrl}")
    private String notifyUrl;

    // 数据库操作
    @Autowired
    private PropertyBillMapper billMapper;
    @Autowired
    private PropertyPaymentMapper paymentMapper;
    @Autowired
    private PropertyHouseMapper houseMapper;

    // JSON解析器
    private final ObjectMapper objectMapper = new ObjectMapper();


    /**
     * 创建支付订单（统一入口，支持微信/支付宝）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayResponseDTO createOrder(PayRequestDTO request) {
        // 1. 校验账单合法性
        PropertyBill bill = validateBill(request.getBillId());
        // 2. 生成商户订单号（唯一）
        String outTradeNo = generateOutTradeNo();

        // 3. 保存支付记录（待支付状态）
        PropertyPayment payment = savePaymentRecord(bill, request.getPayType(), outTradeNo);

        // 4. 根据支付方式调用对应支付接口
        if ("WECHAT".equals(request.getPayType())) {
            return null;
        } else if ("ALIPAY".equals(request.getPayType())) {
            return createAlipayOrder(bill, payment, request.getClientType());
        } else {
            throw new ServiceException("不支持的支付方式：" + request.getPayType());
        }
    }


    /**
     * 处理微信支付回调
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String handleWechatNotify(String xmlData) {
        try {
            // 1. 解析微信回调数据（XML转JSON）
            Map<String, String> notifyMap = xmlToMap(xmlData);
            log.info("微信支付回调解析结果：{}", notifyMap);

            // 2. 校验回调签名（关键！防止伪造请求）
            if (!verifyWechatSign(notifyMap)) {
                log.error("微信支付回调签名验证失败");
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名错误]]></return_msg></xml>";
            }

            // 3. 校验支付状态
            String tradeState = notifyMap.get("trade_state");
            if (!"SUCCESS".equals(tradeState)) {
                log.warn("微信支付未成功，订单号：{}，状态：{}", notifyMap.get("out_trade_no"), tradeState);
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            }

            // 4. 更新订单状态
            String outTradeNo = notifyMap.get("out_trade_no");
            updatePaymentSuccess(outTradeNo, notifyMap.get("transaction_id"), "WECHAT");

            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

        } catch (Exception e) {
            log.error("微信支付回调处理失败", e);
            return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>";
        }
    }


    /**
     * 处理支付宝支付回调
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String handleAlipayNotify(HttpServletRequest request) {
        try {
            // 1. 获取支付宝回调参数
            Map<String, String[]> requestParams = request.getParameterMap();
            Map<String, String> notifyMap = new HashMap<>(16);
            requestParams.forEach((key, values) -> notifyMap.put(key, values[0]));
            log.info("支付宝支付回调解析结果：{}", notifyMap);

            // 2. 校验签名
          /*  boolean signVerified = AlipaySignature.rsaCheckV1(
                    notifyMap,
                    alipayPublicKey,
                    "UTF-8",
                    "RSA2"
            );
            if (!signVerified) {
                log.error("支付宝支付回调签名验证失败");
                return "fail";
            }*/

            // 3. 校验支付状态
            String tradeStatus = notifyMap.get("trade_status");
            if (!"TRADE_SUCCESS".equals(tradeStatus)) {
                log.warn("支付宝支付未成功，订单号：{}，状态：{}", notifyMap.get("out_trade_no"), tradeStatus);
                return "success";
            }

            // 4. 更新订单状态
            String outTradeNo = notifyMap.get("out_trade_no");
            updatePaymentSuccess(outTradeNo, notifyMap.get("trade_no"), "ALIPAY");

            return "success";

        } catch (ServiceException e) {
            log.error("支付宝支付回调处理失败", e);
            return "fail";
        }
    }


    /**
     * 查询支付状态
     */
    @Override
    public PayStatusDTO queryPayStatus(String outTradeNo) {
        // 1. 先查本地数据库
        PropertyPayment payment = paymentMapper.selectByPaymentNo(outTradeNo);
        if (payment == null) {
            throw new ServiceException("订单不存在：" + outTradeNo);
        }

        PayStatusDTO statusDTO = new PayStatusDTO();
        statusDTO.setOutTradeNo(outTradeNo);
        statusDTO.setReceiptNo(payment.getReceiptNo());

        // 2. 已支付直接返回
        if (payment.getPayTime() != null) {
            statusDTO.setIsPaid(true);
            statusDTO.setPayTime(payment.getPayTime());
            return statusDTO;
        }

        // 3. 未支付，查询第三方支付平台
        if ("WECHAT".equals(payment.getPayType())) {
            return queryWechatPayStatus(outTradeNo, statusDTO);
        } else if ("ALIPAY".equals(payment.getPayType())) {
            return queryAlipayPayStatus(outTradeNo, statusDTO);
        }

        return statusDTO;
    }


    /**
     * 关闭未支付订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeOrder(String outTradeNo) {
        // 1. 查询订单
        PropertyPayment payment = paymentMapper.selectByPaymentNo(outTradeNo);
        if (payment == null) {
            throw new ServiceException("订单不存在：" + outTradeNo);
        }

        // 2. 已支付不能关闭
        if (payment.getPayTime() != null) {
            throw new ServiceException("订单已支付，不能关闭");
        }

        // 3. 调用第三方平台关闭订单
        try {
            if ("WECHAT".equals(payment.getPayType())) {
                /*CloseOrderRequest request = new CloseOrderRequest();
                request.setOutTradeNo(outTradeNo);
                jsapiService.closeOrder(request);*/
            } else if ("ALIPAY".equals(payment.getPayType())) {
               /* AlipayTradeCloseRequest request = new com.alipay.api.request.AlipayTradeCloseRequest();
                request.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
                alipayClient.execute(request);*/
            }
        } catch (Exception e) {
            log.error("关闭订单失败：{}", outTradeNo, e);
            throw new ServiceException("关闭订单失败，请重试");
        }

        // 4. 本地标记订单为关闭
        payment.setStatus("CLOSED");
        paymentMapper.updatePropertyPayment(payment);
    }


    /**
     * 批量查询账单支付状态
     */
    @Override
    public List<BillPayStatusDTO> batchQueryBillStatus(List<Long> billIds) {
        if (CollectionUtils.isEmpty(billIds)){
            return Collections.emptyList();
        }
        // 1. 查询账单基本信息
        List<PropertyBill> bills = billMapper.selectBatchIds(billIds);
        if (bills.isEmpty()) {
            return Collections.emptyList();
        }

        // 2. 查询关联的支付记录
        List<Long> billIdList = bills.stream().map(PropertyBill::getBillId).collect(Collectors.toList());
        List<PropertyPayment> payments = paymentMapper.selectByBillIds(billIdList);
        Map<Long, PropertyPayment> paymentMap = payments.stream()
                .collect(Collectors.toMap(PropertyPayment::getBillId, p -> p, (k1, k2) -> k2));

        // 3. 组装结果
        return bills.stream().map(bill -> {
            BillPayStatusDTO dto = new BillPayStatusDTO();
            dto.setBillId(bill.getBillId());
            dto.setBillNo(bill.getBillNo());
            dto.setIsPaid("PAID".equals(bill.getStatus()));

            PropertyPayment payment = paymentMap.get(bill.getBillId());
            if (payment != null && payment.getPayTime() != null) {
                dto.setPayTime(payment.getPayTime());
                dto.setReceiptNo(payment.getReceiptNo());
            }
            return dto;
        }).collect(Collectors.toList());
    }


    // ------------------------------ 私有工具方法 ------------------------------

    /**
     * 校验账单合法性（是否存在、是否已支付、是否属于当前用户）
     */
    private PropertyBill validateBill(Long billId) {
        PropertyBill bill = billMapper.selectPropertyBillByBillId(billId);
        if (bill == null) {
            throw new ServiceException("账单不存在");
        }
        if ("PAID".equals(bill.getStatus())) {
            throw new ServiceException("账单已支付");
        }

        // 校验权限：仅账单所属房屋的业主/租户可支付
        Long userId = SecurityUtils.getUserId();
        PropertyHouse house = houseMapper.selectPropertyHouseByHouseId(bill.getHouseId());
        if (!house.getOwnerId().equals(userId) && !isTenantOfHouse(house.getHouseId(), userId)) {
            throw new ServiceException("无权限支付该账单");
        }

        return bill;
    }

    /**
     * 检查是否为房屋租户
     */
    private boolean isTenantOfHouse(Long houseId, Long userId) {
        // 实际实现需关联租户表查询，此处简化
        return false;
    }

    /**
     * 生成商户订单号（规则：P + 年月日时分秒 + 4位随机数）
     */
    private String generateOutTradeNo() {
        return "P" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
                + new Random().nextInt(9000) + 1000;
    }

    /**
     * 保存支付记录（待支付状态）
     */
    private PropertyPayment savePaymentRecord(PropertyBill bill, String payType, String outTradeNo) {
        PropertyPayment payment = new PropertyPayment();
        payment.setPaymentNo(outTradeNo);
        payment.setBillId(bill.getBillId());
        payment.setUserId(SecurityUtils.getUserId());
        payment.setPayType(payType);
        payment.setPayAmount(bill.getAmount().add(bill.getPenalty())); // 金额 + 违约金
        payment.setStatus("PENDING"); // 待支付
        paymentMapper.insertPropertyPayment(payment);
        return payment;
    }

    /**
     * 创建微信支付订单（最新 SDK 版本）
     */


    /**
     * 创建支付宝支付订单
     */
    private PayResponseDTO createAlipayOrder(PropertyBill bill, PropertyPayment payment, String clientType) {
        try {
            // 1. 构建支付宝请求参数
           /* com.alipay.api.request.AlipayTradePagePayRequest request = new com.alipay.api.request.AlipayTradePagePayRequest();
            // 支付宝回调地址（需公网可访问）
            request.setReturnUrl(returnUrl); // 前端同步回调
            request.setNotifyUrl(notifyUrl); // 后端异步回调

            // 2. 组装业务参数
            Map<String, Object> bizContent = new HashMap<>(8);
            bizContent.put("out_trade_no", payment.getPaymentNo());
            bizContent.put("total_amount", payment.getPayAmount().setScale(2, RoundingMode.HALF_UP)); // 元
            bizContent.put("subject", "物业费-" + bill.getBillNo());
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); // 即时到账
            request.setBizContent(objectMapper.writeValueAsString(bizContent));

            // 3. 调用支付宝SDK生成支付表单（H5）或参数（小程序）
            com.alipay.api.response.AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
            if (!"10000".equals(response.getCode())) {
                throw new ServiceException("创建支付宝订单失败：" + response.getMsg());
            }

            // 4. 构建返回结果
            PayResponseDTO result = new PayResponseDTO();
            result.setBillId(bill.getBillId());
            result.setOutTradeNo(payment.getPaymentNo());
            // H5支付返回表单HTML，小程序返回签名参数（此处简化）
            result.setPayUrl(response.getBody());

            return result;*/

        } catch (Exception e) {
            log.error("支付宝支付下单失败", e);
            throw new ServiceException("创建支付宝支付订单失败：" + e.getMessage());
        }
        return null;
    }

    /**
     * 支付成功后更新订单状态
     */
    private void updatePaymentSuccess(String outTradeNo, String thirdPartyTradeNo, String payType) {
        // 1. 查询支付记录
        PropertyPayment payment = paymentMapper.selectByPaymentNo(outTradeNo);
        if (payment == null) {
            throw new ServiceException("支付记录不存在：" + outTradeNo);
        }
        // 防止重复处理
        if (payment.getPayTime() != null) {
            log.warn("订单已处理过支付成功：{}", outTradeNo);
            return;
        }

        // 2. 更新支付记录
        payment.setPayTime(new Date());
        payment.setThirdPartyTradeNo(thirdPartyTradeNo); // 第三方交易号
        payment.setStatus("SUCCESS");
        payment.setReceiptNo(generateReceiptNo()); // 生成电子收据编号
        paymentMapper.updatePropertyPayment(payment);

        // 3. 更新账单状态为“已支付”
        PropertyBill bill = new PropertyBill();
        bill.setBillId(payment.getBillId());
        bill.setStatus("PAID");
        billMapper.updatePropertyBill(bill);

        log.info("订单支付成功：{}，金额：{}", outTradeNo, payment.getPayAmount());
    }

    /**
     * 查询微信支付状态
     */
    private PayStatusDTO queryWechatPayStatus(String outTradeNo, PayStatusDTO statusDTO) {
        try {
            /*QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
            request.setOutTradeNo(outTradeNo);
            Transaction response = jsapiService.queryOrderByOutTradeNo(request);

            if ("SUCCESS".equals(response.getTradeState())) {
                statusDTO.setIsPaid(true);
                statusDTO.setPayTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",response.getSuccessTime()));
            } else {
                statusDTO.setIsPaid(false);
            }*/
            return statusDTO;
        } catch (ServiceException e) {
            log.error("查询微信支付状态失败", e);
            throw new ServiceException("查询支付状态失败");
        }
    }

    /**
     * 查询支付宝支付状态
     */
    private PayStatusDTO queryAlipayPayStatus(String outTradeNo, PayStatusDTO statusDTO) {
        /*try {
            com.alipay.api.request.AlipayTradeQueryRequest request = new com.alipay.api.request.AlipayTradeQueryRequest();
            request.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
            com.alipay.api.response.AlipayTradeQueryResponse response = alipayClient.execute(request);

            if ("10000".equals(response.getCode()) && "TRADE_SUCCESS".equals(response.getTradeStatus())) {
                statusDTO.setIsPaid(true);
                statusDTO.setPayTime(response.getSendPayDate());
            } else {
                statusDTO.setIsPaid(false);
            }
            return statusDTO;
        } catch (AlipayApiException e) {
            log.error("查询支付宝支付状态失败", e);
            throw new ServiceException("查询支付状态失败");
        }*/
        return null;
    }

    /**
     * 微信回调签名验证
     */
    private boolean verifyWechatSign(Map<String, String> notifyMap) {
        // 实际实现需根据微信支付V3签名规则验证，此处简化
        // 参考：https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
        return true;
    }

    /**
     * XML转Map（微信回调数据解析）
     */
    private Map<String, String> xmlToMap(String xmlData) {
        // 实际实现需用XML解析工具（如Dom4j），此处简化
        return new HashMap<>();
    }

    /**
     * 元转分
     */
    private int convertToCent(BigDecimal amount) {
        return amount.multiply(new BigDecimal(100)).intValue();
    }

    /**
     * 生成电子收据编号
     */
    private String generateReceiptNo() {
        return "R" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                + new Random().nextInt(90000) + 10000;
    }

    /**
     * 获取当前用户的Openid（需从登录信息中获取，实际项目需实现）
     */
    private String getUserOpenid() {
        // 示例：从当前登录用户的扩展信息中获取openid TODO  return SecurityUtils.getLoginUser().getUser().getOpenid();
        return SecurityUtils.getLoginUser().getUser().getUserName();
    }
}